#ifndef KALEIDOSCOPE_FRONTEND_SYNTACTICAL_ANALYSIS_MARSHALL_HPP
#define KALEIDOSCOPE_FRONTEND_SYNTACTICAL_ANALYSIS_MARSHALL_HPP
//=====================================================================
#include <atma/assert.hpp>
#include <kaleidoscope/kaleidoscope.hpp>
//=====================================================================
KALEIDOSCOPE_BEGIN
//=====================================================================

	namespace marshall
	{
		namespace detail
		{
			template <size_t P, typename T>
			T get(T node)
			{
				return *(node->children.begin() + P);
			}
		}
		
		namespace function
		{
			template <typename T> T name(T node) { return node; }
			template <typename T> T return_type(T node) { return detail::get<0>(node); }
			template <typename T> T parameter_list(T node) { return detail::get<1>(node); }
			template <typename T> T body(T node) { return detail::get<2>(node); }
		}
		
		namespace function_call
		{
			template <typename T> T name(T node) { return node; }
			template <typename T> T parameter_list(T node) { return node; }
		}
		
		namespace parameter
		{
			template <typename T> T name(T node) { return node; }
			template <typename T> T type(T node) { return detail::get<0>(node); }
			template <typename T> T default_value(T node) { return detail::get<1>(node); }
		}
		
		namespace argument
		{
			template <typename T> T name(T node) { return node; }
			template <typename T> T type(T node) { return node; }
		}
		
		namespace return_statement
		{
			template <typename T> T expression(T node) { return detail::get<0>(node); }
		}
		
		namespace identifier
		{
			template <typename T> T name(T node) { return node; }
		}
		
		template <typename T> T name(T node)
		{
			if (node->id == ids::function)
				return function::name(node);
			else if (node->id == ids::function_call)
				return function_call::name(node);
			else
				ATMA_ASSERT(false); // this is best.
			
			return T();
		}
		
		template <typename T> T parameter_list(T node)
		{
			if (node->id == ids::function)
				return function::parameter_list(node);
			else if (node->id == ids::function_call)
				return function_call::parameter_list(node);
			else
				ATMA_ASSERT(false);
			
			return T();
		}
		
		template <typename T> T type(T node)
		{
			switch (node->id) {
				case ids::int_literal: return detail::get<0>(node);
				case ids::int_type: return node;
				case ids::parameter: return parameter::type(node);
				case ids::function: return function::return_type(node);
				default: ATMA_ASSERT(false);
			}
			
			return T();
		}
		
		template <typename T> T value(T node)
		{
			switch (node->id) {
				default: return node;
			}
			
			return T();
		}
	}

//=====================================================================
KALEIDOSCOPE_CLOSE
//=====================================================================
#endif
//=====================================================================
